import 'dart:async';
import 'dart:ffi';
import 'dart:isolate';
import 'package:ffi/ffi.dart';
import 'package:win32/win32.dart';

class KeyboardService {
  static ReceivePort? _receivePort;
  static Stream<KeyboardEvent>? _eventStream;
  static SendPort? _sendPort;
  static ReceivePort? _exitReceivePort; // 添加退出接收端口
  static Completer<void>? _exitCompleter;

  static Stream<KeyboardEvent> get eventStream {
    if (_eventStream == null) {
      throw StateError('KeyboardService not initialized');
    }
    return _eventStream!;
  }

  static Isolate? _isolate;

  static Future<void> init() async {
    _receivePort = ReceivePort();
    _exitReceivePort = ReceivePort();
    _exitCompleter = Completer<void>();

    _eventStream = _receivePort!.asBroadcastStream().map((event) {
      return KeyboardEvent.fromMap(event as Map<String, dynamic>);
    });
    _sendPort = _receivePort!.sendPort;

    // 监听退出信号
    _exitReceivePort!.listen((message) {
      if (message == 'EXIT_COMPLETE') {
        _exitCompleter?.complete();
      }
    });

    _isolate = await Isolate.spawn(keyboardListener, (
      _sendPort!,
      _exitReceivePort!.sendPort,
    ));
  }

  static Future<void> dispose() async {
    try {
       // 无论如何都确保清理资源
      if (_isolate != null) {
        _isolate!.kill(priority: Isolate.immediate);
        _isolate = null;
      }
      // 首先调用 stop，通知消息循环退出
      stop();

      // 等待退出完成的信号，设置超时
      await _exitCompleter?.future.timeout(
        const Duration(seconds: 5),
        onTimeout: () {
          print('Timeout waiting for isolate to exit, forcing kill');
        },
      );
    } catch (e) {
      print('Error during graceful shutdown: $e');
    } finally {
      // 无论如何都确保清理资源
      if (_isolate != null) {
        _isolate!.kill(priority: Isolate.immediate);
        _isolate = null;
      }

      _receivePort?.close();
      _receivePort = null;

      _exitReceivePort?.close();
      _exitReceivePort = null;

      _eventStream = null;
      _sendPort = null;
      _exitCompleter = null;

      // 确保全局变量也被清理
      _isRunning = false;
      _globalSendPort = null;
      _globalExitPort = null;
      if (_globalHook != null && _globalHook != 0) {
        UnhookWindowsHookEx(_globalHook!);
        _globalHook = null;
      }
    }
  }
}

class KeyboardEvent {
  final String keyName;
  final int vkCode;
  final int scanCode;
  final bool isKeyDown;

  KeyboardEvent({
    required this.keyName,
    required this.vkCode,
    required this.scanCode,
    required this.isKeyDown,
  });

  Map<String, dynamic> toMap() {
    return {
      'keyName': keyName,
      'vkCode': vkCode,
      'scanCode': scanCode,
      'isKeyDown': isKeyDown,
    };
  }

  factory KeyboardEvent.fromMap(Map<String, dynamic> map) {
    return KeyboardEvent(
      keyName: map['keyName'],
      vkCode: map['vkCode'],
      scanCode: map['scanCode'],
      isKeyDown: map['isKeyDown'],
    );
  }
}

// 修改全局变量
SendPort? _globalSendPort;
SendPort? _globalExitPort;
int? _globalHook;
bool _isRunning = true;

// 静态回调函数
int _lowLevelKeyboardProc(int nCode, int wParam, int lParam) {
  if (nCode >= 0 && _globalSendPort != null && _isRunning) {
    final kbd = Pointer<KBDLLHOOKSTRUCT>.fromAddress(lParam);
    final vkCode = kbd.ref.vkCode;
    final scanCode = kbd.ref.scanCode;
    final flags = kbd.ref.flags;
    final isKeyDown = wParam == WM_KEYUP || wParam == WM_SYSKEYUP;

    if (isKeyDown) {
      final keyName = getKeyName(vkCode, scanCode, flags);
      _globalSendPort!.send(
        KeyboardEvent(
          keyName: keyName,
          vkCode: vkCode,
          scanCode: scanCode,
          isKeyDown: isKeyDown,
        ).toMap(),
      );
    }
  }
  return CallNextHookEx(NULL, nCode, wParam, lParam);
}

void keyboardListener((SendPort, SendPort) ports) {
  final (sendPort, exitPort) = ports;
  _globalSendPort = sendPort;
  _globalExitPort = exitPort;

  _globalHook = SetWindowsHookEx(
    WH_KEYBOARD_LL,
    Pointer.fromFunction<HOOKPROC>(_lowLevelKeyboardProc, 0),
    GetModuleHandle(nullptr),
    0,
  );

  if (_globalHook == 0) {
    print('Failed to set keyboard hook');
    _globalExitPort?.send(null);
    return;
  }

  print('Keyboard hook installed. Press keys to see output...');

  final msg = malloc<MSG>();
  final windowClassName = 'KeyboardListenerWindow'.toNativeUtf16(
    allocator: malloc,
  );

  // 使用正确的 Win32 类型
  final wndClass = calloc<WNDCLASS>();

  try {
    // 初始化窗口类
    wndClass.ref.style = 0;
    wndClass.ref.lpfnWndProc = Pointer.fromFunction<WindowProc>(
      DefWindowProc,
      0,
    );
    wndClass.ref.cbClsExtra = 0;
    wndClass.ref.cbWndExtra = 0;
    wndClass.ref.hInstance = GetModuleHandle(nullptr);
    wndClass.ref.hIcon = NULL;
    wndClass.ref.hCursor = NULL;
    wndClass.ref.hbrBackground = NULL;
    wndClass.ref.lpszClassName = windowClassName;
    wndClass.ref.lpszMenuName = nullptr;

    // 注册窗口类
    if (RegisterClass(wndClass) == 0) {
      print('Failed to register window class');
      return;
    }

    // 创建窗口
    final hwnd = CreateWindowEx(
      0,
      // dwExStyle
      windowClassName,
      // lpClassName
      nullptr,
      // lpWindowName
      0,
      // dwStyle
      0,
      // X
      0,
      // Y
      0,
      // nWidth
      0,
      // nHeight
      NULL,
      // hWndParent
      NULL,
      // hMenu
      GetModuleHandle(nullptr),
      // hInstance
      nullptr, // lpParam
    );

    if (hwnd == 0) {
      print('Failed to create window');
      return;
    }

    // 消息循环
    while (_isRunning && GetMessage(msg, NULL, 0, 0) != 0) {
      TranslateMessage(msg);
      DispatchMessage(msg);
    }

    // 清理窗口
    if (hwnd != 0) {
      DestroyWindow(hwnd);
    }
    UnregisterClass(windowClassName, GetModuleHandle(nullptr));
  } finally {
    // 清理资源
    if (_globalHook != null && _globalHook != 0) {
      UnhookWindowsHookEx(_globalHook!);
    }

    malloc.free(windowClassName);
    free(wndClass);
    free(msg);

    _globalHook = null;
    _globalSendPort = null;
    _globalExitPort = null;

    // 发送退出完成信号
    exitPort.send('EXIT_COMPLETE');
  }
}

// 添加一个方法来设置退出标志
void stopKeyboardListener() {
  _isRunning = false;
  // 发送一个 WM_QUIT 消息来退出消息循环
  PostQuitMessage(0);
}

// KeyboardService 中添加停止方法
void stop() {
  _isRunning = false;
  PostQuitMessage(0);
}

String getKeyName(int vkCode, int scanCode, int flags) {
  switch (vkCode) {
    // 特殊字符和符号
    case 0xC0: // VK_OEM_3 - 反引号/波浪号键 (`/~)
      return (flags & 0x01) == 0 ? '`' : '~';
    case 0xBD: // VK_OEM_MINUS - 减号/下划线键 (-/_)
      return (flags & 0x01) == 0 ? '-' : '_';
    case 0xBB: // VK_OEM_PLUS - 等号/加号键 (=/+)
      return (flags & 0x01) == 0 ? '=' : '+';
    case 0xDB: // VK_OEM_4 - 左方括号/左花括号键 ([/{)
      return (flags & 0x01) == 0 ? '[' : '{';
    case 0xDD: // VK_OEM_6 - 右方括号/右花括号键 (]/})
      return (flags & 0x01) == 0 ? ']' : '}';
    case 0xDC: // VK_OEM_5 - 反斜杠/竖线键 (\|)
      return (flags & 0x01) == 0 ? '\\' : '|';
    case 0xBA: // VK_OEM_1 - 分号/冒号键 (;/:)
      return (flags & 0x01) == 0 ? ';' : ':';
    case 0xDE: // VK_OEM_7 - 单引号/双引号键 ('/')
      return (flags & 0x01) == 0 ? '\'' : '"';
    case 0xBC: // VK_OEM_COMMA - 逗号/小于号键 (,/<)
      return (flags & 0x01) == 0 ? ',' : '<';
    case 0xBE: // VK_OEM_PERIOD - 句号/大于号键 (./>)
      return (flags & 0x01) == 0 ? '.' : '>';
    case 0xBF: // VK_OEM_2 - 斜杠/问号键 (/?)
      return (flags & 0x01) == 0 ? '/' : '?';

    // 控制键
    case VK_CONTROL:
    case VK_LCONTROL:
    case VK_RCONTROL:
      return 'CTRL';
    case VK_SHIFT:
    case VK_LSHIFT:
    case VK_RSHIFT:
      return 'SHIFT';
    case VK_MENU:
    case VK_LMENU:
    case VK_RMENU:
      return 'ALT';
    case VK_RETURN:
      return 'ENTER';
    case VK_ESCAPE:
      return 'ESC';
    case VK_SPACE:
      return 'SPACE';
    case VK_TAB:
      return 'TAB';
    case VK_BACK:
      return 'BACKSPACE';
    case VK_DELETE:
      return 'DELETE';

    // 方向键
    case VK_LEFT:
      return 'LEFT ARROW';
    case VK_RIGHT:
      return 'RIGHT ARROW';
    case VK_UP:
      return 'UP ARROW';
    case VK_DOWN:
      return 'DOWN ARROW';

    // 数字键（主键盘）
    case 0x30: // 0
    case 0x31: // 1
    case 0x32: // 2
    case 0x33: // 3
    case 0x34: // 4
    case 0x35: // 5
    case 0x36: // 6
    case 0x37: // 7
    case 0x38: // 8
    case 0x39: // 9
      return String.fromCharCode(vkCode);

    // 小键盘数字键
    case VK_NUMPAD0:
      return 'NUMPAD 0';
    case VK_NUMPAD1:
      return 'NUMPAD 1';
    case VK_NUMPAD2:
      return 'NUMPAD 2';
    case VK_NUMPAD3:
      return 'NUMPAD 3';
    case VK_NUMPAD4:
      return 'NUMPAD 4';
    case VK_NUMPAD5:
      return 'NUMPAD 5';
    case VK_NUMPAD6:
      return 'NUMPAD 6';
    case VK_NUMPAD7:
      return 'NUMPAD 7';
    case VK_NUMPAD8:
      return 'NUMPAD 8';
    case VK_NUMPAD9:
      return 'NUMPAD 9';

    // 功能键
    case VK_F1:
      return 'F1';
    case VK_F2:
      return 'F2';
    case VK_F3:
      return 'F3';
    case VK_F4:
      return 'F4';
    case VK_F5:
      return 'F5';
    case VK_F6:
      return 'F6';
    case VK_F7:
      return 'F7';
    case VK_F8:
      return 'F8';
    case VK_F9:
      return 'F9';
    case VK_F10:
      return 'F10';
    case VK_F11:
      return 'F11';
    case VK_F12:
      return 'F12';

    // 其他特殊键
    case VK_CAPITAL:
      return 'CAPS LOCK';
    case VK_NUMLOCK:
      return 'NUM LOCK';
    case VK_SCROLL:
      return 'SCROLL LOCK';
    case VK_SNAPSHOT:
      return 'PRINT SCREEN';
    case VK_PAUSE:
      return 'PAUSE';
    case VK_APPS:
      return 'APPLICATION';

    default:
      // 字母键 A-Z
      if (vkCode >= 0x41 && vkCode <= 0x5A) {
        return String.fromCharCode(vkCode);
      }
      return 'VK: $vkCode';
  }
}
